using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using Matrix.ServiceDiscovery.Dtos;
using Matrix.ServiceDiscovery.Entities;

namespace Matrix.ServiceDiscovery.Services
{
    /// <summary>
    /// 服务发现查询服务
    /// 专注于高性能读取和缓存优化
    /// </summary>
    public class ServiceDiscoveryQueryService : ApplicationService
    {
        private readonly IServiceInfoRepository _serviceRepository;
        private readonly ServiceDiscoveryCacheService _cacheService;
        private readonly ILogger<ServiceDiscoveryQueryService> _logger;

        public ServiceDiscoveryQueryService(
            IServiceInfoRepository serviceRepository,
            ServiceDiscoveryCacheService cacheService,
            ILogger<ServiceDiscoveryQueryService> logger)
        {
            _serviceRepository = serviceRepository;
            _cacheService = cacheService;
            _logger = logger;
        }

        /// <summary>
        /// 根据ID获取服务信息
        /// </summary>
        public async Task<ServiceInfoDto> GetAsync(Guid id)
        {
            var cacheKey = ServiceDiscoveryCacheService.GetServiceCacheKey(id);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var service = await _serviceRepository.GetAsync(id);
                return ObjectMapper.Map<ServiceInfo, ServiceInfoDto>(service);
            }, TimeSpan.FromMinutes(30));
        }

        /// <summary>
        /// 根据服务名称获取服务信息
        /// </summary>
        public async Task<ServiceInfoDto> GetByNameAsync(string serviceName)
        {
            var cacheKey = ServiceDiscoveryCacheService.GetByNameCacheKey(serviceName);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var service = await _serviceRepository.GetByNameAsync(serviceName);
                if (service == null)
                {
                    throw new Volo.Abp.BusinessException("ServiceDiscovery:ServiceNotFound")
                        .WithData("ServiceName", serviceName);
                }

                return ObjectMapper.Map<ServiceInfo, ServiceInfoDto>(service);
            }, TimeSpan.FromMinutes(30));
        }

        /// <summary>
        /// 获取服务列表
        /// </summary>
        public async Task<PagedResultDto<ServiceInfoDto>> GetListAsync(GetServiceListInput input)
        {
            var cacheKey = ServiceDiscoveryCacheService.GetListCacheKey(input);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var queryable = await _serviceRepository.GetQueryableAsync();

                // 动态查询构建
                queryable = queryable
                    .WhereIf(!input.ServiceType.IsNullOrWhiteSpace(), x => x.ServiceType.ToString() == input.ServiceType)
                    .WhereIf(!input.ServiceGroup.IsNullOrWhiteSpace(), x => x.ServiceGroup == input.ServiceGroup)
                    .WhereIf(input.Status.HasValue, x => x.Status == input.Status.Value)
                    .WhereIf(!input.Keyword.IsNullOrWhiteSpace(),
                        x => x.Name.Contains(input.Keyword) || x.Description.Contains(input.Keyword));

                var totalCount = await AsyncExecuter.CountAsync(queryable);

                var items = await AsyncExecuter.ToListAsync(
                    queryable.OrderBy(x => x.ServiceGroup).ThenBy(x => x.Name)
                        .PageBy(input.SkipCount, input.MaxResultCount)
                );

                return new PagedResultDto<ServiceInfoDto>(
                    ObjectMapper.Map<List<ServiceInfo>, List<ServiceInfoDto>>(items),
                    totalCount
                );
            }, TimeSpan.FromMinutes(10));
        }

        /// <summary>
        /// 获取服务的所有实例
        /// </summary>
        public async Task<ListResultDto<ServiceInstanceDto>> GetInstancesAsync(Guid serviceId)
        {
            var cacheKey = ServiceDiscoveryCacheService.GetInstancesCacheKey(serviceId);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var instances = await _serviceRepository.GetInstancesAsync(serviceId);
                return new ListResultDto<ServiceInstanceDto>(
                    ObjectMapper.Map<List<ServiceInstance>, List<ServiceInstanceDto>>(instances)
                );
            }, TimeSpan.FromMinutes(5));
        }

        /// <summary>
        /// 根据服务名称获取健康实例
        /// </summary>
        public async Task<ListResultDto<ServiceInstanceDto>> GetHealthyInstancesAsync(string serviceName)
        {
            var cacheKey = ServiceDiscoveryCacheService.GetHealthyInstancesCacheKey(serviceName);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var instances = await _serviceRepository.GetHealthyInstancesAsync(serviceName);
                return new ListResultDto<ServiceInstanceDto>(
                    ObjectMapper.Map<List<ServiceInstance>, List<ServiceInstanceDto>>(instances)
                );
            }, TimeSpan.FromMinutes(2));
        }

        /// <summary>
        /// 获取负载均衡配置
        /// </summary>
        public async Task<LoadBalancingConfigDto> GetLoadBalancingConfigAsync(Guid serviceId)
        {
            var cacheKey = ServiceDiscoveryCacheService.GetLoadBalancingConfigCacheKey(serviceId);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var config = await _serviceRepository.GetLoadBalancingConfigAsync(serviceId);
                return ObjectMapper.Map<LoadBalancingConfig, LoadBalancingConfigDto>(config);
            }, TimeSpan.FromMinutes(30));
        }

        /// <summary>
        /// 获取服务健康检查记录
        /// </summary>
        public async Task<PagedResultDto<HealthCheckRecordDto>> GetHealthCheckRecordsAsync(
            Guid serviceInstanceId,
            GetHealthCheckRecordsInput input)
        {
            var cacheKey = ServiceDiscoveryCacheService.GetHealthRecordsCacheKey(serviceInstanceId, input);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var records = await _serviceRepository.GetHealthCheckRecordsAsync(
                    serviceInstanceId,
                    input.StartTime,
                    input.EndTime,
                    input.MaxResultCount);

                var totalCount = records.Count;

                var pagedRecords = records
                    .OrderByDescending(x => x.CheckTime)
                    .Skip(input.SkipCount)
                    .Take(input.MaxResultCount)
                    .ToList();

                return new PagedResultDto<HealthCheckRecordDto>(
                    ObjectMapper.Map<List<HealthCheckRecord>, List<HealthCheckRecordDto>>(pagedRecords),
                    totalCount
                );
            }, TimeSpan.FromMinutes(5));
        }

        /// <summary>
        /// 搜索服务
        /// </summary>
        public async Task<PagedResultDto<ServiceInfoDto>> SearchServicesAsync(SearchServicesInput input)
        {
            // 搜索结果通常缓存时间较短
            var cacheKey = ServiceDiscoveryCacheService.GetSearchCacheKey(input);

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var queryable = await _serviceRepository.GetQueryableAsync();

                if (!input.Keyword.IsNullOrWhiteSpace())
                {
                    queryable = queryable.Where(x =>
                        x.Name.Contains(input.Keyword) ||
                        x.Description.Contains(input.Keyword) ||
                        x.ServiceGroup.Contains(input.Keyword));
                }

                if (input.ServiceTypes?.Any() == true)
                {
                    queryable = queryable.Where(x => input.ServiceTypes.Contains(x.ServiceType.ToString()));
                }

                if (input.Statuses?.Any() == true)
                {
                    queryable = queryable.Where(x => input.Statuses.Contains(x.Status));
                }

                var totalCount = await AsyncExecuter.CountAsync(queryable);

                var items = await AsyncExecuter.ToListAsync(
                    queryable.OrderByDescending(x => x.LastModificationTime)
                        .PageBy(input.SkipCount, input.MaxResultCount)
                );

                return new PagedResultDto<ServiceInfoDto>(
                    ObjectMapper.Map<List<ServiceInfo>, List<ServiceInfoDto>>(items),
                    totalCount
                );
            }, TimeSpan.FromMinutes(2));
        }

        /// <summary>
        /// 获取服务统计信息
        /// </summary>
        public async Task<ServiceStatisticsDto> GetServiceStatisticsAsync()
        {
            var cacheKey = ServiceDiscoveryCacheService.GetStatisticsCacheKey();

            return await _cacheService.GetOrSetAsync(cacheKey, async () =>
            {
                var statistics = await _serviceRepository.GetServiceStatisticsAsync();
                return statistics;
            }, TimeSpan.FromMinutes(5));
        }
    }
}